
package smart.utils
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.utils.Dictionary;
	import flash.utils.describeType;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	
	
	
	import smart.injector.Injector;
	
	/**
	 *ReflectUtil.as：
	 *<p>反射工具</p>
	 *@author:Eric li
	 *@date:2012-4-15
	 */
	public class ReflectUtil
	{
		
		/**
		 *描述XML 
		 */
		private var descriptXML:XML;
		/**
		 *cache容器 
		 */		
		private var reflectCache:Dictionary;
		/**
		 * ReflectUtil实例 
		 */		
		private static var _instance:ReflectUtil;
		
		/**
		 * 构造反射实例 
		 * 
		 */		
		public function ReflectUtil()
		{
			reflectCache = new Dictionary();
		}
		/**
		 * 映射素材 
		 * 
		 */		
		public static function map2Res(reflectInstance:DisplayObject,resouce:DisplayObjectContainer):void
		{
			if(!_instance)
			{
				_instance = new ReflectUtil();
			}
			_instance.reflect(reflectInstance,resouce);
		}
		/**
		 * 将实际素材映射到目标Sprite上 
		 * @param desc
		 * @param orgiRes
		 * 
		 */		
		private function reflect(target:Object,orgiRes:DisplayObjectContainer):void
		{
			this.descriptXML = describeTypeCache(target);
			var list : XMLList = descriptXML.*;
			var item : XML;
			//缓存容器
			var propMap:Dictionary = new Dictionary();
			for each (item in list) {
				var itemName : String = item.name().toString();
				switch(itemName) {
					case "variable":
						propMap[item.@name.toString()] = item.@type.toString();
						break;
					case "accessor":
						var access : String = item.@access;
						if((access == "readwrite") || (access == "writeonly")) {
							propMap[item.@name.toString()] = item.@type.toString();
						}
						break;
				}
			}
			for(var prop:String in propMap)
			{
				var obj:Object = this.map(prop,orgiRes);
				target[prop] = obj!=null ? obj : target[prop];
			}
		}
		/**
		 * 映射素材元件
		 * @param property
		 * @param resouce
		 * 
		 */		
		private function map(property:String,resouce:DisplayObjectContainer):DisplayObject
		{
			var res:DisplayObject = resouce.getChildByName(property);
			return res;
		}
		private static var valueDic:Dictionary=new Dictionary();
		
		public static function mapValue(askClass:Class,injectClass:Class):void
		{
			var askc:String=flash.utils.getQualifiedClassName(askClass);
			var injuectc:String=flash.utils.getQualifiedClassName(injectClass);
			valueDic[askc]=injuectc;
		}
		
		public static function getInjecClass(askClassType:String):String
		{
			if(valueDic[askClassType]==null)
			{
				return askClassType;
			}else{
				return valueDic[askClassType];
			}
		}
		
		
		public static function reflectObj(target:Object,orgiRes:Object):void
		{
			var injector:Injector=SingletonClassFactory.getSingletonInstance(Injector) as Injector;
			
			var descriptXML:XML = describeType(orgiRes);
			var list : XMLList = descriptXML.*;
			var item : XML;
			//缓存容器
			var propMap:Dictionary = new Dictionary();
			var injectorMap:Dictionary=new Dictionary();
			for each (item in list) {
				var itemName : String = item.name().toString();
				switch(itemName) {
					case "variable":
						var name:String=item.@name.toString();
						var type:String=item.@type.toString();
						if(item.metadata[0])
						{
							var metaName:String=item.metadata[0].@name.toString();
							if(metaName.toLocaleLowerCase()=="inject")
							{
								//trace(name);
								type=getInjecClass(type);
								var cls:Class=getDefinitionByName(type) as Class;
								var value:Object=injector.getValue(type);
								if(value!=null)
								{  
									injectorMap[name]=value;
								}else
								{
									injectorMap[name]=SingletonClassFactory.getSingletonInstance(cls) as cls;
									
								}
								
							}
						}
						
						
						propMap[item.@name.toString()] = item.@type.toString();
						break;
					case "accessor":
						var access : String = item.@access;
						if((access == "readwrite") || (access == "writeonly")) {
							propMap[item.@name.toString()] = item.@type.toString();
						}
						break;
					case "matedata":
						propMap[item.@name.toString()] = item.@type.toString();
						break;
				}
			}
			for(var prop:String in injectorMap)
			{
				var obj:Object = injectorMap[prop];
				orgiRes[prop] = obj!=null ? obj : target[prop];
			}
		}
		
		/**
		 * 获取xml描述 
		 * @param desc
		 * @return 
		 * 
		 */		
		private function describeTypeCache(desc:Object):XML
		{
			var name:String = getQualifiedClassName(desc);
			
			if(!this.reflectCache[name])
			{
				this.reflectCache[name] = describeType(desc);
			}
			return this.reflectCache[name];
		}
		
	}
}